package main.java.com.stylinlin.object;

import java.io.*;
import java.util.Objects;

/**
 * JonlinObject
 *
 * @author jonlin
 * @date 2020/6/30
 */
public class JonlinObject implements Serializable, Cloneable {
    private int id;
    private String name;
    private ItemObject itemObject;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ItemObject getItemObject() {
        return itemObject;
    }

    public void setItemObject(ItemObject itemObject) {
        this.itemObject = itemObject;
    }

    public JonlinObject(int id, String name, ItemObject itemObject) {
        this.id = id;
        this.name = name;
        this.itemObject = itemObject;
    }

    public JonlinObject() {
    }

    /**
     * object equals默认比较内存地址
     *
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        JonlinObject that = (JonlinObject) o;
        return id == that.id &&
                Objects.equals(name, that.name);
    }

    /**
     * 重写equals，必须重写hashCode()，否则在使用hashSet等用到hashCode()方法的地方时会出错
     * equals为true 则hashCode必须相等，反之则不然
     * 哈希码:hash是把任意长度的输入（又叫做预映射pre-image）通过散列算法变换成固定长度的输出，该输出就是散列值。这种转换是一种压缩映射，也就是，散列值的空间通常远小于输入的空间，不同的输入可能会散列成相同的输出，所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
     *
     * @return
     */
    @Override
    public int hashCode() {
//        return id%10;

//        int idHash = Integer.valueOf(id).hashCode();
//        System.out.println("值'" + id + "'的hashcode：" + idHash);
//
//        int nameHash = name.hashCode();
//        System.out.println("值'" + name + "'的hashcode：" + nameHash);
//
//        int objectHash =  (31 * (31 * 1 + idHash) + nameHash);
//        System.out.println("对象的hashcode：" + objectHash);
        return Objects.hash(id, name);
    }

    /**
     * 需要显式地clone其引用成员。
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object o = super.clone();
        ItemObject itemObject = ((JonlinObject)o).getItemObject();
        ((JonlinObject)o).setItemObject((ItemObject)itemObject.clone());
        return o;
    }

    public JonlinObject deepClone() {
        JonlinObject p2=null;
        JonlinObject p1=this;
        PipedOutputStream out=new PipedOutputStream();
        PipedInputStream in=new PipedInputStream();
        try {
            in.connect(out);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
                out.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        try(ObjectOutputStream bo=new ObjectOutputStream(out);
            ObjectInputStream bi=new ObjectInputStream(in);) {
            bo.writeObject(p1);
            p2=(JonlinObject) bi.readObject();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return p2;
    }



//    @Override
//    protected Object clone() throws CloneNotSupportedException {
//        return super.clone();
//    }


    @Override
    public String toString() {
        return "JonlinObject{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", itemObject=" + itemObject +
                '}';
    }
}
